package cn.apthink.utility;

import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class DateUtil {
	public final static DateTimeFormatter df8 = DateTimeFormatter.ofPattern("yyyyMMdd");
	public final static DateTimeFormatter df14 = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
	public final static DateTimeFormatter df19 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
	public final static DateTimeFormatter df10 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
	public final static DateTimeFormatter df7 = DateTimeFormatter.ofPattern("yyyy-MM");
	public final static DateTimeFormatter df5 = DateTimeFormatter.ofPattern("MM/dd");
	public final static DateTimeFormatter dfw = DateTimeFormatter.ofPattern("w");

	/**
	 * C#时间戳字符串转换标准日期时间格式
	 *
	 * @param s
	 * @return
	 */
	public static String cstampToDate(String s) {
		String res;
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String st = s.substring(s.indexOf("Date(") + 5, s.indexOf(")"));
		long lt = Long.valueOf(st);
		Date date = new Date(lt);
		res = simpleDateFormat.format(date);
		return res;
	}

	/**
	 * 时间字符串（HH:MM/HH:MM:SS)转秒(距当天00:00:00的秒数）
	 *
	 * @param s
	 * @return
	 */
	public static int Time2Second(String s) {
		String[] t = s.split(":");
		int result = 0;
		if (t.length == 2) {
			result = Util.Str2Int(t[0]) * 60 * 60 + Util.Str2Int(t[1]) * 60;
		} else if (t.length == 3) {
			result = Util.Str2Int(t[0]) * 60 * 60 + Util.Str2Int(t[1]) * 60 + Util.Str2Int(t[2]);
		}
		return result;
	}

	public static long timediff(LocalDateTime start, LocalDateTime end) {
		return Duration.between(start, end).toMillis() / 1000;
	}

	public static int daydiff(String start, String end) {
		LocalDate s = toDate(start);
		LocalDate e = toDate(end);
		return (int) s.until(e, ChronoUnit.DAYS);
	}

	public static int compareTo(String start, String end) {
		LocalDate s = toDate(start);
		LocalDate e = toDate(end);
		return s.isAfter(e) ? -1 : s.isBefore(e) ? 1 : 0;
	}

	/**
	 * 当前系统时间字符串
	 *
	 * @return
	 */
	public static String now() {
		return toDateTimeStr(LocalDateTime.now());
	}

	/**
	 * 当前系统时间戳
	 *
	 * @return
	 */
	public static String timeStamp() {
		return LocalDateTime.now().format(df14);
	}

	/**
	 * 当前系统日期字符串
	 *
	 * @return
	 */
	public static String today() {
		return toDateStr(LocalDate.now());
	}

	public static String todayAfter(int days) {
		return toDateStr(LocalDate.now().plusDays(days));
	}

	/**
	 * 逗号分隔字符串转List
	 *
	 * @param strs
	 * @return
	 */
	public static List<Integer> stringToList(String strs) {
		String str[] = strs.split(",");
		List<Integer> list = new ArrayList<Integer>();
		for (String element : str) {
			list.add(Util.Str2Int(element));
		}
		return list;
	}

	/**
	 * 字符串转LocatDate
	 *
	 * @param s
	 * @return
	 */
	public static LocalDate toDate(String s) {
		LocalDate result;
		try {
			if (Util.isEmpty(s)) {
				result = null;
			} else {
				String d = s.length() > 10 ? s.substring(0, 10) : s;
				result = LocalDate.parse(d, df10);
			}
		} catch (Exception e) {
			result = null;
		}
		return result;
	}

	public static LocalDateTime toDateTime(String s) {
		LocalDateTime result;
		try {
			if (Util.isEmpty(s)) {
				result = null;
			} else if (s.length() == 8) {
				result = LocalDate.parse(s, df8).atStartOfDay();
			} else if (s.length() == 10) {
				result = LocalDate.parse(s, df10).atStartOfDay();
			} else if (s.length() == 14) {
				result = LocalDateTime.parse(s, df14);
			} else {
				result = LocalDateTime.parse(s, df19);
			}
		} catch (Exception e) {
			result = null;
		}
		return result;
	}

	public static String toDateTimeStr(LocalDateTime dt) {
		return dt.format(df19);
	}

	public static String toMonthStr(LocalDate dt) {
		return dt.format(df7);
	}

	public static String toShortDateTimeStr(LocalDateTime dt) {
		return dt.format(df14);
	}

	public static String toDateStr(LocalDateTime dt) {
		return dt.format(df10);
	}

	public static String toDateStr(LocalDate dt) {
		return dt.format(df10);
	}

	public static String toMonthDayStr(LocalDate dt) {
		return dt.format(df5);
	}

	public static String toShortDateStr(String strDate) {
		LocalDate dt = toDate(strDate);
		return dt.format(df8);
	}

	public static boolean betweenRange(String d, String s, String e) {
		LocalDate c = toDate(d);
		LocalDate sd = toDate(s);
		LocalDate ed = toDate(e);
		return c.isAfter(sd) && c.isBefore(ed);
	}

	public static String getFirstDayOfMonth(int year, int month) {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.YEAR, year);
		cal.set(Calendar.MONTH, month - 1);
		int firstDay = cal.getActualMinimum(Calendar.DAY_OF_MONTH);
		cal.set(Calendar.DAY_OF_MONTH, firstDay);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		String firstDayOfMonth = sdf.format(cal.getTime());
		return firstDayOfMonth;
	}

	public static String getLastDayOfMonth(int year, int month) {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.YEAR, year);
		cal.set(Calendar.MONTH, month - 1);
		int lastDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
		cal.set(Calendar.DAY_OF_MONTH, lastDay);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		String lastDayOfMonth = sdf.format(cal.getTime());
		return lastDayOfMonth;
	}

	/**
	 * Get number of days between two dates
	 *
	 * @param first  first date
	 * @param second second date
	 * @return number of days if first date less than second date, 0 if first date
	 *         is bigger than second date, 1 if dates are the same
	 */
	public static int getNumberOfDays(Date first, Date second) {
		int compare = first.compareTo(second);
		if (compare > 0) {
			return 0;
		} else if (compare == 0) {
			return 1;
		}

		Calendar calendar = Calendar.getInstance();
		calendar.setTime(first);

		int firstDay = calendar.get(Calendar.DAY_OF_YEAR);
		int firstYear = calendar.get(Calendar.YEAR);
		int firstDays = calendar.getActualMaximum(Calendar.DAY_OF_YEAR);

		calendar.setTime(second);

		int secondDay = calendar.get(Calendar.DAY_OF_YEAR);
		int secondYear = calendar.get(Calendar.YEAR);

		int result = 0;

		// if dates in the same year
		if (firstYear == secondYear) {
			result = secondDay - firstDay + 1;
		} else {
			// days from the first year
			result += firstDays - firstDay + 1;

			// add days from all years between the two dates years
			for (int i = firstYear + 1; i < secondYear; i++) {
				calendar.set(i, 0, 0);
				result += calendar.getActualMaximum(Calendar.DAY_OF_YEAR);
			}

			// days from last year
			result += secondDay;
		}

		return result;
	}

	public static LocalDateTime timestamToDatetime(long timestamp) {
		Instant instant = Instant.ofEpochMilli(timestamp);
		return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
	}

	public static String timestamToDatetimeStr(long timestamp) {
		Instant instant = Instant.ofEpochMilli(timestamp);
		return toDateTimeStr(LocalDateTime.ofInstant(instant, ZoneId.systemDefault()));
	}

}
